/*
 * Copyright (C) 2018 FoilPlanet Inc.
 */

#pragma once

#include "device.h"

namespace anbox {
namespace input {

struct DeviceState;

class DeviceMonitor : public std::enable_shared_from_this<DeviceMonitor> {
public:

    static std::shared_ptr<DeviceMonitor> create(
        const std::shared_ptr<Device> &device, const std::shared_ptr<Runtime> &runtime
    );

    DeviceMonitor(const std::shared_ptr<Device> &device);

    ~DeviceMonitor();

    DeviceState &get_state() {
        return *state_;
    }

    void sync_abs_configuration();

    bool parse_input(const std::vector<std::uint8_t> &data);

    static std::string socket_file();

private:
    int next_id() {
        return next_connection_id_++;
    };

    void new_client(
        std::shared_ptr<boost::asio::local::stream_protocol::socket> const &socket
    );

    std::shared_ptr<Device> device_;
    std::unique_ptr<DeviceState> state_;

    std::atomic<int> next_connection_id_;
    std::shared_ptr<network::PublishedSocketConnector> connector_;
    std::shared_ptr<network::Connections<network::SocketConnection>> connections_;
};

class InputMessageProcessor : public network::MessageProcessor {
  private:
    DeviceMonitor *dm_;

  public:
    InputMessageProcessor(DeviceMonitor *dev) : dm_(dev) {};
    ~InputMessageProcessor() {};

    bool process_data(const std::vector<std::uint8_t> &data) override {
        if (nullptr != dm_) {
            return dm_->parse_input(data);
        }
        return false;
    }
};

}  // namespace input
}  // namespace anbox
